using System;
using OhioState.Math;

namespace OhioState.Graphics.Proxy
{
    /// <summary>
    /// BoundingSphere Class
    /// </summary>
    [Serializable()]
    public class BoundingSphere : IBoundingVolume, ICloneable
    {
        private float _radius;
        /// <summary>
        /// Get/set Accessor for Radius of the bounding sphere
        /// </summary>
        public float Radius
        {
            get { return _radius; }
            set { _radius = value; }
        }
        private Vector3 _position;
        /// <summary>
        /// Get/Set accessor for the position of the bounding sphere
        /// </summary>
        public Vector3 Position
        {
            get { return _position; }
            set { _position = value; }
        }
        
        /// <summary>
        /// Create a bounding sphere with radius 1 and 
        /// position at the origin (0, 0, 0)
        /// </summary>
        public BoundingSphere()
            : this(1.0f, new Vector3())
        {
        }

        /// <summary>
        /// Create a bounding sphere with the given 
        /// radius and position at the origin (0, 0, 0)
        /// </summary>
        /// <param name="radius">The radius of the bounding sphere.</param>
        public BoundingSphere(float radius)
            : this(radius, new Vector3())
        {
        }

        /// <summary>
        /// Create a bounding sphere with the given radius
        /// and position.
        /// </summary>
        /// <param name="radius">The radius of the bounding sphere.</param>
        /// <param name="position">The position of the bounding sphere.</param>
        public BoundingSphere(float radius, Vector3 position)
        {
            _radius = radius;
            _position = position;
        }
        /// <summary>
        /// Create a copy of the sphere
        /// </summary>
        /// <returns></returns>
        public Object Clone()
        {
            BoundingSphere bSphere = new BoundingSphere(_radius, _position);
            return bSphere;
        }
        /// <summary>
        /// Overrides shared object ToString method
        /// </summary>
        /// <returns>A string representing parent shared object name</returns>
        public override string ToString()
        {
            return "Not implemented yet.";
        }

        #region IBoundingVolume interface
        /// <summary>
        /// Implementation of IBoundingVolume Centroid Get Accessor
        /// </summary>
        public Vector3 Centroid
        {
            get
            {
                return new Vector3(_position);
            }
        }
        /// <summary>
        /// Implementation of IboundingVolume ContainsPoint method
        /// </summary>
        /// <param name="point">input point</param>
        /// <returns>true or false</returns>
        public bool ContainsPoint(Vector3 point)
        {
            bool inside = point.dot(_position) <= (_radius*_radius);
            return inside;
        }
        /// <summary>
        /// Implementation of IBoundingVolume ClosestPoint method
        /// </summary>
        /// <param name="target"></param>
        /// <returns></returns>
        public Vector3 ClosestPoint(Vector3 target)
        {
            Vector3 direction = target - _position;
            direction.normalize();
            Vector3 point = _radius * (_position + direction);
            return point;
        }
        #endregion IBoundingVolume interface
    }
}
